package cc.owoo.godpen.analysis.css;

import cc.owoo.godpen.analysis.html.Element;

import java.util.LinkedList;
import java.util.Queue;

/**
 * 单条CSS选择器
 * Created by nimensei
 * 2022-05-30 下午 10:14
 **/
public class SelectorSingle extends Selector {
    private final LinkedList<SelectorNode> selectorNodes = new LinkedList<>();// 选择器节点
    private boolean isLastChild;// 最后一个节点是否为子元素选择器

    /**
     * 添加一个选择器节点
     *
     * @param selectorNode 选择器节点对象
     */
    public void append(SelectorNode selectorNode) {
        if (selectorNode == null)
            throw new NullPointerException("选择器节点不能为空");
        if (selectorNode == CHILD_SELECTOR) {
            if (selectorNodes.size() == 0)
                return;
            isLastChild = true;
            return;
        }
        if (isLastChild) {
            selectorNodes.add(CHILD_SELECTOR);
            isLastChild = false;
        }
        selectorNodes.add(selectorNode);
    }

    @Override
    public void select(Queue<Element> elements) {
        if (elements == null || elements.size() == 0)
            return;
        boolean isChild = true;
        for (SelectorNode node : selectorNodes) {
            int size = elements.size();
            if (node == CHILD_SELECTOR) {
                isChild = true;
                continue;
            }
            while (--size >= 0) {
                Element element = elements.remove();
                if (element == null)
                    continue;
                if (isChild)
                    node.selectElement(element, elements);
                else
                    node.matchingElement(element, elements);
            }
            isChild = false;
            if (elements.size() == 0)
                break;
        }
    }

    /**
     * 获取选择器节点数量
     *
     * @return 选择器节点数量
     */
    public int size() {
        return selectorNodes.size();
    }

    @Override
    public boolean stringify(StringBuilder string, String retract, boolean format) {
        if (string == null || selectorNodes.size() == 0)
            return false;
        if (format && retract != null)
            string.append(retract);
        for (SelectorNode node : selectorNodes)
            node.stringify(string);
        return true;
    }

    @Override
    public String toString() {
        return stringify();
    }
}
